/*
 * Copyright 2009 Jsanca <jsanca at gmail.com>
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package siena.dbslayer;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import siena.AbstractPersistenceManager;
import siena.Query;

/**
 * Persistence Manager for DBSlayer (http://code.nytimes.com/projects/dbslayer).
 * The idea behind this persistence manager is create the SQL sentences, send via siena remote and 
 * parser and blind the Json to the Model objects.
 * @author jsanca
 *
 */
public class DBSlayerPersistenceManager extends AbstractPersistenceManager {

	private GenericSQLPlainStatementBuilder statementBuilder = new GenericSQLPlainStatementBuilder ();
	
	private Map<Class<?>, ClassInfo> infoClasses = new HashMap<Class<?>, ClassInfo> ();
	
	/**
	 * Constructor.
	 */
	public DBSlayerPersistenceManager() {

		super ();
	} // DBSlayerPersistenceManager.

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#beginTransaction(int)
	 */
	public void beginTransaction(int isolationLevel) {

	}

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#closeConnection()
	 */
	public void closeConnection() {

	}

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#commitTransaction()
	 */
	public void commitTransaction() {

	}

	public ClassInfo getClassInfo(Object model) {
		ClassInfo ci = infoClasses.get(model);
		if(ci == null) {
			ci = new ClassInfo(model);
			infoClasses.put(model.getClass(), ci);
		}
		return ci;
	}
	
	/* (non-Javadoc)
	 * @see siena.PersistenceManager#createQuery(java.lang.Class)
	 */
	public <T> Query<T> createQuery(Class<T> clazz) {
		
		
		return null;
	} // createQuery.

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#delete(siena.Model)
	 */
	public void delete(Object model) {
		
		Map<String, String> fieldColumnIds = this.getClassInfo(model).getFieldColumnIds();
		List<String> keyColumns = this.createKeyColumns (model, fieldColumnIds);
		String deleteSQL = this.statementBuilder.createDelete(model, keyColumns);
		
		// TODO: Send the message by Siena Remote and receive too, after bind the result.
	} // delete.

	private List<String> createKeyColumns(Object model, Map<String, String> fieldColumnIds) {
		
		List<String> keyColumns = new ArrayList<String> ();
		Field field = null;
		StringBuilder builder = null;
		Object value = null;

		for (java.util.Map.Entry<String, String> fieldColumnIdEntry : fieldColumnIds.entrySet()) {
			
		  	field = ReflectionUtil.getField(model.getClass(), fieldColumnIdEntry.getKey());
		  	builder = new StringBuilder ();
		  	builder.append(fieldColumnIdEntry.getValue()).append("=");
		  	
		  	value = ReflectionUtil.getValue(field, model);
		  	
		  	builder = (field.getType() == CharSequence.class)?
		  		builder.append("'").append(value).append("'"):
		  	    builder.append(value);
		  		
		  	keyColumns.add(builder.toString());
		}
		
		return keyColumns;
	} // createKeyColumns.

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#get(siena.Model)
	 */
	public void get(Object obj) {

		
	}

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#init(java.util.Properties)
	 */
	public void init(Properties p) {

	}

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#insert(siena.Model)
	 */
	public void insert(Object obj) {

	}

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#rollbackTransaction()
	 */
	public void rollbackTransaction() {

	}

	/* (non-Javadoc)
	 * @see siena.PersistenceManager#update(siena.Model)
	 */
	public void update(Object obj) {

	}

	class ClassInfo {
		
		public ClassInfo(Object model) {
			
			this.fieldColumnIds = ModelHelper.getPropertyColumnNameIds(model);
		} // ClassInfo.
		
		private Map<String, String> fieldColumnIds = new HashMap<String, String> ();
		
		public Map<String, String> getFieldColumnIds () {
			
			return this.fieldColumnIds;
		}
	} // ClassInfo.
} // E:OF:DBSlayerPersistenceManager.
